# Copyright (c) 2022 Presto Labs Pte. Ltd.
# Author: qiang

import datetime
import requests
import json
from coin2.exchange.product_info import ProductInfoDefault
from coin2.exchange.symbology import SymbologyInfo
from coin.exchange.ftx_futures.kr_rest.contract_util import find_contract_type_from_expiry


def last_friday_of_month(year, month):
  if month == 12:
    next_month = datetime.datetime(
        year=year + 1,
        month=1,
        day=1,
        hour=8)
  else:
    next_month = datetime.datetime(
        year=year,
        month=month + 1,
        day=1,
        hour=8)
  this_month_last_day = next_month - datetime.timedelta(days=1)
  day = this_month_last_day
  while True:
    if day.weekday() == 4:
      break
    day = day - datetime.timedelta(days=1)
  return day


def quarter_expiration(trading_datetime):
  quarter_month = ((trading_datetime.month // 4 + 1) % 5) * 3
  this_quater_friday = last_friday_of_month(trading_datetime.year, quarter_month)
  if trading_datetime > this_quater_friday:
    if quarter_month == 12:
      return last_friday_of_month(trading_datetime.year + 1, 3)
    else:
      return last_friday_of_month(trading_datetime.year, quarter_month + 3)
  else:
    return this_quater_friday

def next_quarter_expiration(trading_datetime):
  return quarter_expiration(quarter_expiration(trading_datetime) + datetime.timedelta(days=1))

def nnext_quarter_expiration(trading_datetime):
  return quarter_expiration(next_quarter_expiration(trading_datetime) + datetime.timedelta(days=1))

def to_expire(info, expire_to_norm):
  expiration = datetime.datetime.fromtimestamp(int(info["deliveryTime"]) / 1000)
  for item in expire_to_norm:
    if expiration == item:
      expiration = item
      break
  return expire_to_norm[expiration]

def generate():
  mea = 'Futures.Bybit.v3'
  me = 'Futures.Bybit'
  default = ProductInfoDefault()
  symbol_info = SymbologyInfo()
  parame = {"category": "inverse"}
  data = requests.get("https://api.bybit.com/derivatives/v3/public/instruments-info", params=parame).json()['result']["list"]

  now = datetime.datetime.now()
  quarter = quarter_expiration(now)
  next_quarter = next_quarter_expiration(now)
  nnext_quarter = nnext_quarter_expiration(now)

  expire_to_norm = {
      quarter: "QUARTER",
      next_quarter: "NEXT_QUARTER",
  #    nnext_quarter: "NNEXT_QUARTER",
  }

  pis = []
  for info in data:
    native_symbol = info['symbol']
    contract_type = info["contractType"]
    native_base = info['baseCoin']
    native_quote = info['quoteCoin']
    base = symbol_info.native_to_norm_currency(mea, native_base)
    quote = symbol_info.native_to_norm_currency(mea, native_quote)

    if "Perpetual" in contract_type:
      symbol = "%s-%s.PERPETUAL" % (base, quote)
    else:
      try:
        contract_type = to_expire(info, expire_to_norm)
        symbol = "%s-%s.%s" % (base, quote, contract_type)
      except KeyError as e:
        print("[%s] ignore symbol: %s, expiry_date: %s" % (mea, native_symbol, e))
        continue

    pi = dict(
        symbol=symbol,
        base=base,
        quote=quote,
        native_symbol=native_symbol,
        native_base=native_base,
        native_quote=native_quote,
        price_ticksize=float(info['priceFilter']['tickSize']),
        qty_ticksize=float(info['lotSizeFilter']['qtyStep']),
        contract_value=float(1),
        is_inverse= True,
    )

    pi = {**pi, **default.product_info(me, symbol)}
    pis.append(pi)

  pis = sorted(pis, key=lambda x: x['symbol'])
  return pis


if __name__ == "__main__":
  import json
  print(json.dumps(generate(), indent=2))
